from minio import Minio
from minio.error import InvalidResponseError
import urllib3
import time,os
from datetime import datetime,timedelta
# from minio import CopyConditions

# obj = {
#     "host":'192.168.1.105:9000',
#     "access_key":"P7I5CDZIBK3E3HLRX6J3",
#     "secret_key":"8Mw3VH4RyXxWP54PGLxRS0C9lIEtmwK3Rtvvg8h9"
# }
obj = {
    "host":'162.55.15.176:9000',
    "access_key":"JEEPIQU07SX0X5NHLINP",
    "secret_key":"x+cLtoxZxLXu7NmZ+D8KgIRad1KobXhY08l2PCC3"
}

class Client(object):
    '''
    minio 功能封装
    '''
    def __init__(self,host,access_key,secret_key):
        self.minioClient = Minio(host,
                        access_key=access_key,
                        secret_key=secret_key,
                        secure=False
                        )
    # 创建一个存储桶
    def make_bucket(self,bucket_name,location='cn-north-1'):
        try:
           return self.minioClient.make_bucket(bucket_name, location=location)
        except InvalidResponseError as err:
            print(err)
    
    # 列出所有的存储桶
    def list_buckets(self):
        return self.minioClient.list_buckets()
    
    
    # 检查存储桶是否存在
    def bucket_exists(self,bucket_name):
        try:
            return self.minioClient.bucket_exists(bucket_name)
        except InvalidResponseError as err:
            print(err)
    
    # 删除存储桶
    def remove_bucket(self,bucket_name):
        try:
            return self.minioClient.remove_bucket(bucket_name)
        except InvalidResponseError as err:
            print(err)

    
    # 列出存储通中的所有对象 
    def list_objects(self,bucket_name,prefix=None,recursive=False):
        '''
        bucket_name  string	存储桶名称。
        prefix      string	用于过滤的对象名称前缀。可选项，默认为None。
        recursive   bool    True代表递归查找，False代表类似文件夹查找，以'/'分隔，不查子文件夹。（可选，默认值是False）。

        return:
            object 该存储桶中所有对象的Iterator，对象的格式如下：
                object.bucket_name	    string	对象所在存储桶的名称。
                object.object_name	    string	对象的名称。
                object.is_dir           bool    True代表列举的对象是文件夹（对象前缀）， False与之相反。
                object.size	            int	对象的大小。
                object.etag	            string	对象的etag值。
                object.last_modified	datetime.datetime	最后修改时间。
                object.content_type	    string	对象的content-type。
                object.metadata	        dict	对象的其它元数据。
        '''
        return self.minioClient.list_objects(bucket_name, prefix=prefix, recursive=recursive)

    # 列出存储桶中未完整上传的对象
    def list_incomplete_uploads(self,bucket_name, prefix=None, recursive=False):
        '''
        bucket_name  string	存储桶名称。
        prefix      string	用于过滤的对象名称前缀。可选项，默认为None。
        recursive   bool    True代表递归查找，False代表类似文件夹查找，以'/'分隔，不查子文件夹。（可选，默认值是False）。

        return:
            multipart_obj	Object	multipart对象的Iterator，格式如下：
                multipart_obj.object_name	string	未完整上传的对象的名称。
                multipart_obj.upload_id	    string	未完整上传的对象的上传ID。
                multipart_obj.size	        int	未完整上传的对象的大小。
        '''
        return self.minioClient.list_incomplete_uploads(bucket_name, prefix=prefix, recursive=recursive)
    
    # 下载并将文件保存到本地
    def fget_object(self,bucket_name, object_name, file_path, request_headers=None):
        '''
        bucket_name	string	存储桶名称。
        object_name	string	对象名称。
        file_path	dict	对象数据要写入的本地文件路径。
        request_headers	dict	额外的请求头信息 （可选，默认为None）。

        return:
            obj	Object	对象的统计信息，格式如下：
                obj.size	        int	对象的大小。
                obj.etag	        string	对象的etag值。
                obj.content_type	string	对象的Content-Type。
                obj.last_modified	time.time	最后修改时间。
                obj.metadata	    dict	对象的其它元数据。
        '''
        try:            
            return self.minioClient.fget_object(bucket_name, object_name, file_path)
        except InvalidResponseError as err:
            print(err)
        
    # 拷贝对象存储服务上的源对象到一个新对象
    def copy_object(self,bucket_name, object_name, object_source, copy_conditions=None, metadata=None):
        '''
        本API支持的最大文件大小是5GB。
            bucket_name	    string	新对象的存储桶名称。
            object_name	    string	新对象的名称。
            object_source	string	要拷贝的源对象的存储桶名称+对象名称。
            copy_conditions	CopyConditions	拷贝操作需要满足的一些条件（可选，默认为None）。

            minioClient.copy_object("mybucket", "myobject",
                                    "/my-sourcebucketname/my-sourceobjectname",
                                    copy_conditions,metadata=metadata)
        '''
        try:
            copy_result = self.minioClient.copy_object(bucket_name, object_name,
                                                object_source,
                                                copy_conditions,metadata=metadata)
            return copy_result
        except InvalidResponseError as err:
            print(err)
            
    # 添加一个新的对象到对象存储服务。
    def put_object(self,bucket_name,file_url, object_name, content_type='application/octet-stream', metadata=None):
        '''
        注意：本API支持的最大文件大小是5TB。
            bucket_name	    string	存储桶名称。
            file_url        string  文件路径
            object_name	    string	对象名称。
            data	        io.RawIOBase	任何实现了io.RawIOBase的python对象。
            length	        int	对象的总长度。
            content_type	string	对象的Content type。（可选，默认是“application/octet-stream”）。
            metadata	    dict	其它元数据。（可选，默认是None）。

        return:
            etag	string	对象的etag值。

        实例：
            with open('my-testfile.csv', 'rb') as file_data:
            file_stat = os.stat('my-testfile.csv')
            minioClient.put_object('mybucket', 'myobject.csv', file_data,
                        file_stat.st_size, content_type='application/csv')
        '''
        try:
            with open(file_url, 'rb') as file_data:
                file_stat = os.stat(file_url)
                length = file_stat.st_size
                return self.minioClient.put_object(bucket_name, object_name, file_data,
                            length, content_type=content_type,metadata=metadata)
        except InvalidResponseError as err:
            print(err)
                
    # 通过文件上传到对象中
    def fput_object(self,bucket_name, object_name, file_path, content_type='application/octet-stream', metadata=None):
        '''
        bucket_name	string	存储桶名称。
        object_name	string	对象名称。
        file_path	string	本地文件的路径，会将该文件的内容上传到对象存储服务上。
        content_type	string	对象的Content type（可选，默认是“application/octet-stream”）。
        metadata	dict	其它元数据（可选，默认是None）。

        return:
            etag	string	对象的etag值。
        
        实例：
        print(minioClient.fput_object('mybucket', 'myobject.csv',
                    '/tmp/otherobject.csv',
                    content_type='application/csv'))
        '''
        try:
            return self.minioClient.fput_object(bucket_name, object_name,
                                    file_path,
                                    content_type=content_type,metadata=metadata)
        except InvalidResponseError as err:
            print(err)

    # 获取对象信息
    def stat_object(self,bucket_name, object_name):
        '''
        bucket_name	        string	存储桶名称。
        object_name	        string	名称名称。‎
        
        return:
            obj	Object	对象的统计信息，格式如下：
                obj.size	int	对象的大小。
                obj.etag	string	对象的etag值。
                obj.content_type	string	对象的Content-Type。
                obj.last_modified	time.time	UTC格式的最后修改时间。
                obj.metadata	dict	对象的其它元数据信息。
        '''
        try:
            return self.minioClient.stat_object(bucket_name, object_name)
        except InvalidResponseError as err:
            print(err)
    
    # 获取对象的标签配置
    def get_object_tags(self,bucket_name,object_name):
        return self.minioClient.get_object_tags(bucket_name,object_name)
    
    # 删除一个对象
    def remove_object(self,bucket_name, object_name):
        '''
        bucket_name	string	存储桶名称。
        object_name	string	名称名称。
        '''
        try:
            return self.minioClient.remove_object(bucket_name, object_name)
        except InvalidResponseError as err:
            print(err)
    
    # 删除存储桶中的多个对象
    def remove_objects(self,bucket_name, objects_iter):
        '''
        bucket_name	    string	                    存储桶名称。
        objects_iter	list , tuple or iterator	多个对象名称的列表数据。

        实例：
        objects_to_delete = ['myobject-1', 'myobject-2', 'myobject-3']
        for del_err in minioClient.remove_objects('mybucket', objects_to_delete):
            print(del_err)
        '''
        try:
            return self.minioClient.remove_objects(bucket_name, objects_iter)
        except InvalidResponseError as err:
            print(err)
    
    # 删除一个未完整上传的对象
    def remove_incomplete_upload(self,bucket_name, object_name):
        '''
        bucket_name	string	存储桶名称。
        object_name	string	对象名称。
        '''
        try:
            return self.minioClient.remove_incomplete_upload(bucket_name, object_name)
        except InvalidResponseError as err:
            print(err)
    
    # 生成一个用于HTTP GET操作的presigned URL
    def presigned_get_object(self,bucket_name, object_name, expiry=timedelta(days=7)):
        '''
        生成一个用于HTTP GET操作的presigned URL。浏览器/移动客户端可以在即使存储桶为私有的情况下也可以通过这个URL进行下载。
        这个presigned URL可以有一个过期时间，默认是7天。

        bucket_name	string	存储桶名称。
        object_name	string	对象名称。
        expiry	datetime.datetime	过期时间，单位是秒，默认是7天。
        '''
        try:
            return self.minioClient.presigned_get_object(bucket_name, object_name,expiry)
        except InvalidResponseError as err:
            print(err)


if __name__ == '__main__':
    minioClient = Client(obj['host'],obj["access_key"],obj["secret_key"])     
    # print(minioClient.make_bucket('snsnb'))
    # print(minioClient.list_buckets())
    # print(minioClient.bucket_exists('discuz'))
    # print(minioClient.list_objects('discuz'))
    bucket_name = 'datab'
    object_name = '2022/ask_banner_m123.jpg'
    file_path = 'ask_banner_m.jpg'
    res = minioClient.fput_object(bucket_name, object_name, file_path,content_type="image/jpeg")
    # print(res.__dict__)
    # print(minioClient.presigned_get_object(bucket_name,object_name))
    # res = minioClient.stat_object(bucket_name,object_name)
    
    print(res)
    





